home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / system-config-printer / pysmb.py < prev    next >
Text File  |  2008-10-20  |  14KB  |  496 lines

  1. #!/usr/bin/python
  2.  
  3. ## system-config-printer
  4. ## CUPS backend
  5.  
  6. ## Copyright (C) 2002, 2003, 2006, 2007, 2008 Red Hat, Inc.
  7. ## Copyright (C) 2002, 2003, 2006, 2007, 2008 Tim Waugh <twaugh@redhat.com>
  8.  
  9. ## This program is free software; you can redistribute it and/or modify
  10. ## it under the terms of the GNU General Public License as published by
  11. ## the Free Software Foundation; either version 2 of the License, or
  12. ## (at your option) any later version.
  13.  
  14. ## This program is distributed in the hope that it will be useful,
  15. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. ## GNU General Public License for more details.
  18.  
  19. ## You should have received a copy of the GNU General Public License
  20. ## along with this program; if not, write to the Free Software
  21. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  
  23. USE_OLD_CODE=False
  24. try:
  25.     import smbc
  26. except ImportError:
  27.     USE_OLD_CODE=True
  28.  
  29. import errno
  30. import gobject
  31. import gtk
  32. import os
  33. import pwd
  34. from debug import *
  35.  
  36. class AuthContext:
  37.     def __init__ (self, parent=None, workgroup='', user='', passwd=''):
  38.         self.passes = 0
  39.         self.has_failed = False
  40.         self.auth_called = False
  41.         self.tried_guest = False
  42.         self.cancel = False
  43.         self.use_user = user
  44.         self.use_password = passwd
  45.         self.use_workgroup = workgroup
  46.         self.parent = parent
  47.  
  48.     def perform_authentication (self):
  49.         self.passes += 1
  50.         if self.passes == 1:
  51.             return 1
  52.  
  53.         if not self.has_failed:
  54.             return 0
  55.  
  56.         debugprint ("pysmb: authentication pass: %d" % self.passes)
  57.         if not self.auth_called:
  58.             debugprint ("pysmb: auth callback not called?!")
  59.             self.cancel = True
  60.             return 0
  61.  
  62.         self.has_failed = False
  63.         if self.auth_called and not self.tried_guest:
  64.             self.use_user = 'guest'
  65.             self.use_password = ''
  66.             self.tried_guest = True
  67.             debugprint ("pysmb: try auth as guest")
  68.             return 1
  69.  
  70.         self.auth_called = False
  71.  
  72.         # After that, prompt
  73.         d = gtk.Dialog ("Authentication", self.parent,
  74.                         gtk.DIALOG_MODAL | gtk.DIALOG_NO_SEPARATOR,
  75.                         (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
  76.                          gtk.STOCK_OK, gtk.RESPONSE_OK))
  77.         d.set_default_response (gtk.RESPONSE_OK)
  78.         d.set_border_width (6)
  79.         d.set_resizable (False)
  80.         hbox = gtk.HBox (False, 12)
  81.         hbox.set_border_width (6)
  82.         image = gtk.Image ()
  83.         image.set_from_stock (gtk.STOCK_DIALOG_AUTHENTICATION,
  84.                               gtk.ICON_SIZE_DIALOG)
  85.         hbox.pack_start (image, False, False, 0)
  86.         vbox = gtk.VBox (False, 12)
  87.         label = gtk.Label ('<span weight="bold" size="larger">' +
  88.                            "You must log in to access %s." % self.for_server +
  89.                            '</span>')
  90.         label.set_use_markup (True)
  91.         label.set_alignment (0, 0)
  92.         label.set_line_wrap (True)
  93.         vbox.pack_start (label, False, False, 0)
  94.  
  95.         table = gtk.Table (3, 2)
  96.         table.set_row_spacings (6)
  97.         table.set_col_spacings (6)
  98.         table.attach (gtk.Label ("Username:"), 0, 1, 0, 1, 0, 0)
  99.         username_entry = gtk.Entry ()
  100.         table.attach (username_entry, 1, 2, 0, 1, 0, 0)
  101.         table.attach (gtk.Label ("Domain:"), 0, 1, 1, 2, 0, 0)
  102.         domain_entry = gtk.Entry ()
  103.         table.attach (domain_entry, 1, 2, 1, 2, 0, 0)
  104.         table.attach (gtk.Label ("Password:"), 0, 1, 2, 3, 0, 0)
  105.         password_entry = gtk.Entry ()
  106.         password_entry.set_activates_default (True)
  107.         password_entry.set_visibility (False)
  108.         table.attach (password_entry, 1, 2, 2, 3, 0, 0)
  109.         vbox.pack_start (table, False, False, 0)
  110.         hbox.pack_start (vbox, False, False, 0)
  111.         d.vbox.pack_start (hbox)
  112.         d.show_all ()
  113.  
  114.         if self.use_user == 'guest':
  115.             self.use_user = pwd.getpwuid (os.getuid ())[0]
  116.             debugprint ("pysmb: try as %s" % self.use_user)
  117.         username_entry.set_text (self.use_user)
  118.         domain_entry.set_text (self.use_workgroup)
  119.         response = d.run ()
  120.         d.hide ()
  121.  
  122.         if response == gtk.RESPONSE_CANCEL:
  123.             self.cancel = True
  124.             return -1
  125.  
  126.         self.use_user = username_entry.get_text ()
  127.         self.use_password = password_entry.get_text ()
  128.         self.use_workgroup = domain_entry.get_text ()
  129.         return 1
  130.  
  131.     def initial_authentication (self):
  132.         try:
  133.             context = smbc.Context ()
  134.             self.use_workgroup = context.workgroup
  135.         except:
  136.             pass
  137.  
  138.     def failed (self, exc=None):
  139.         self.has_failed = True
  140.         debugprint ("pysmb: operation failed: %s" % repr (exc))
  141.  
  142.         if exc:
  143.             if (self.cancel or
  144.                 (type (exc) == RuntimeError and
  145.                  not (exc.args[0] in [errno.EACCES, errno.EPERM]))):
  146.                     raise exc
  147.  
  148.     def callback (self, server, share, workgroup, user, password):
  149.         debugprint ("pysmb: got password callback")
  150.         self.auth_called = True
  151.         self.for_server = server
  152.         self.for_share = share
  153.         if self.passes == 1:
  154.             self.initial_authentication ()
  155.  
  156.         if self.use_user:
  157.             if self.use_workgroup:
  158.                 workgroup = self.use_workgroup
  159.  
  160.             return (workgroup, self.use_user, self.use_password)
  161.  
  162.         user = ''
  163.         password = ''
  164.         return (workgroup, user, password)
  165.  
  166. ###########################
  167. ######## OLD CODE #########
  168. ###########################
  169. import os
  170. import sys
  171. import re
  172.  
  173. nmblookup = "/usr/bin/nmblookup"
  174. smbclient = "/usr/bin/smbclient"
  175.  
  176. wins = None
  177.  
  178. def get_wins_server():
  179.         smbconf = "/etc/samba/smb.conf"
  180.         wsregex = re.compile("\s*wins\s*server.*",re.IGNORECASE)
  181.     
  182.     global wins    
  183.  
  184.     if wins:
  185.         return
  186.     
  187.         try:    
  188.                 file = open(smbconf, 'r')
  189.         except IOError:
  190.                 return
  191.  
  192.         for l in file.readlines():
  193.                 t = l.splitlines()
  194.                 if wsregex.match(t[0]):
  195.                         sp = t[0].split('=');
  196.                         winslist = sp[1] 
  197.                         winslist = winslist.lstrip()
  198.                         winslist = winslist.rstrip()
  199.          
  200.                         file.close()
  201.                         winstab = winslist.split(",")
  202.                 # for now we only take the first wins server 
  203.             wins = winstab[0]
  204.          
  205.         file.close()
  206.         return
  207.  
  208. def get_domain_list ():
  209.     domains = {}
  210.     global wins
  211.  
  212.     if not os.access (smbclient, os.X_OK):
  213.         return domains
  214.  
  215.     get_wins_server()
  216.  
  217.     ips = []
  218.     if wins:
  219.         os.environ['WINS'] = wins
  220.         str = 'LC_ALL=C %s -U "$WINS" -M -- - 2>&1' % (nmblookup)
  221.     else:
  222.         str = "LC_ALL=C %s -M -- - 2>&1" % (nmblookup)
  223.     for l in os.popen (str, 'r').readlines ():
  224.     l = l.splitlines()[0]
  225.     if l.endswith("<01>"):
  226.             ips.append (l.split(" ")[0])
  227.     if len (ips) <= 0:
  228.         if wins:
  229.         os.environ['WINS'] = wins
  230.             str = 'LC_ALL=C %s -U "$WINS" "*" 2>&1' % (nmblookup)
  231.     else:
  232.             str = "LC_ALL=C %s '*' 2>&1" % (nmblookup)
  233.     for l in os.popen (str, 'r').readlines ():
  234.             l = l.splitlines()[0]
  235.         ips.append (l.split(" ")[0])
  236.  
  237.     for ip in ips:
  238.         dom = None
  239.         dict = { 'IP': ip }
  240.     os.environ["IP"] = ip
  241.     if wins:
  242.         os.environ["WINS"] = wins
  243.             str = 'LC_ALL=C %s -U "$WINS" -A "$IP"' % (nmblookup)
  244.     else:
  245.             str = 'LC_ALL=C %s -A "$IP"' % (nmblookup)
  246.     str += " 2>&1"
  247.     for line in os.popen(str, 'r').readlines():
  248.         line = line.splitlines()[0]
  249.         if (line.find(" <00> ") != -1) and (line.find("<GROUP>") != -1):
  250.             dom = line.split(" ")[0]
  251.             dom = dom.lstrip()
  252.             dict['IP'] = ip
  253.             dict['DOMAIN'] = dom
  254.                 
  255.     if dom:
  256.         domains[dom] = dict
  257.     
  258.     return domains
  259.  
  260.  
  261. def get_host_list(dmbip):
  262.         serverlist = 0
  263.     hosts = {}
  264.     list = []
  265.     global wins
  266.         shareregex = re.compile("\s*Sharename\s*Type\s*Comment")
  267.         serverregex = re.compile("\s*Server\s*Comment")
  268.         domainregex = re.compile("\s*Workgroup\s*Master")
  269.         commentregex = re.compile("(\s*-+)+")
  270.     os.environ["DMBIP"] = dmbip
  271.     str = 'LC_ALL=C %s -N -L "//$DMBIP" 2>/dev/null' % (smbclient)
  272.         for l in os.popen (str, 'r').readlines ():
  273.                 l = l.splitlines()[0]
  274.  
  275.                 if serverregex.match(l):
  276.                         serverlist = 1
  277.                 elif shareregex.match(l):
  278.                         serverlist = 0
  279.                 elif domainregex.match(l):
  280.                         serverlist = 0
  281.                 elif commentregex.match(l):
  282.                         continue
  283.                 elif serverlist == 1:
  284.             l = l.split (" ")[0].lstrip()
  285.             if not l:
  286.                             continue
  287.             list.append(l)
  288.  
  289.     for name in list:    
  290.         dict = { 'NAME': name }
  291.         # if there are a lot of servers it takes too much time
  292.         # so commented out
  293.         #
  294.         #if wins:
  295.         #    str = nmblookup + " -U " + wins + " " +name
  296.         #else:
  297.         #    str = nmblookup + " " + name
  298.             #for l in os.popen (str, 'r').readlines ():
  299.         #    if l.endswith("<00>") != False:
  300.         #        dict['IP'] = l.split(" ")[0]
  301.         #    else:
  302.         #        continue
  303.         
  304.         hosts[name] = dict
  305.  
  306.     return hosts
  307.  
  308. def get_host_list_from_domain (domain):
  309.     hosts = {}
  310.     global wins
  311.     ips = []
  312.     if wins:
  313.         str = "LC_ALL=C %s -U %s -R '%s' 2>&1" % (nmblookup, wins, domain)
  314.     else:
  315.         str = "LC_ALL=C %s -R '%s' 2>&1" % (nmblookup, domain)
  316.     for l in os.popen (str, 'r').readlines ():
  317.     l = l.splitlines()[0]
  318.     if l.endswith("<00>"):
  319.             ips.append (l.split(" ")[0])
  320.  
  321.     for ip in ips:
  322.         name = None
  323.         dict = { 'IP': ip }
  324.     os.environ["IP"] = ip
  325.     if wins:
  326.             os.environ["WINS"] = wins
  327.             str = 'LC_ALL=C %s -U "$WINS" -A "$IP"' % (nmblookup)
  328.     else:
  329.             str = 'LC_ALL=C %s -A "$IP"' % (nmblookup)
  330.     str += " 2>&1"
  331.     for line in os.popen(str, 'r').readlines():
  332.         line = line.splitlines()[0]
  333.         if (line.find(" <00> ") != -1) and (line.find("<GROUP>") == -1):
  334.             name = line.split(" ")[0]
  335.             name = name.lstrip()
  336.             dict['NAME'] = name
  337.             dict['DOMAIN'] = domain
  338.                 
  339.     if name:
  340.         hosts[name] = dict
  341.     
  342.     return hosts
  343.  
  344.  
  345. def get_host_info (smbname):
  346.     """Given an SMB name, returns a host dict for it."""
  347.     dict = { 'NAME': smbname, 'IP': '', 'GROUP': '' }
  348.     global wins
  349.     os.environ["SMBNAME"] = smbname
  350.     if wins:
  351.         os.environ["WINS"] = wins
  352.         str = 'LC_ALL=C %s -U "$WINS" -S "$SMBNAME" 2>&1' % (nmblookup)
  353.     else:
  354.         str = 'LC_ALL=C %s -S "$SMBNAME" 2>&1' % (nmblookup)
  355.     for l in os.popen (str, 'r').readlines ():
  356.         l = l.strip ()
  357.         if l.endswith ("<00>"):
  358.             dict['IP'] = l.split (" ")[0]
  359.             continue
  360.  
  361.         if l.find (" <00> ") == -1:
  362.             continue
  363.  
  364.         if l.find (" <GROUP> ") != -1:
  365.             dict['GROUP'] = l.split (" ")[0]
  366.         else:
  367.             name = l.split (" ")[0]
  368.             dict['NAME'] = name
  369.  
  370.     return dict
  371.  
  372. def get_printer_list (host):
  373.     """Given a host dict, returns a dict of printer shares for that host.
  374.     The value for a printer share name is its comment."""
  375.  
  376.     printers = {}
  377.     if not os.access (smbclient, os.X_OK):
  378.         return printers
  379.  
  380.     os.environ["NAME"] = host['NAME']
  381.     str = 'LC_ALL=C %s -N -L "$NAME" 2>&1' % (smbclient)
  382.     if host.has_key ('IP'):
  383.     os.environ["IP"] = host['IP']
  384.     str += ' -I "$IP"'
  385.  
  386.     if host.has_key ('GROUP'):
  387.         os.environ["GROUP"] = host['GROUP']
  388.         str += ' -W "$GROUP"'
  389.  
  390.     section = 0
  391.     typepos = 0
  392.     commentpos = 0
  393.     for l in os.popen (str, 'r'):
  394.         l = l.strip ()
  395.         if l == "":
  396.             continue
  397.  
  398.         if l[0] == '-':
  399.             section += 1
  400.             if section > 1:
  401.                 break
  402.  
  403.             continue
  404.  
  405.     if section == 0:
  406.         if l.find ("Sharename ") != -1:
  407.             typepos = l.find (" Type ") + 1
  408.                 commentpos = l.find (" Comment") + 1
  409.         continue
  410.  
  411.         if section != 1:
  412.         continue
  413.  
  414.         share = l[:l[typepos:].find (" " + "Printer".ljust (commentpos - typepos, " ")) + typepos].strip ()
  415.     if share == -1 and share.endswith (" Printer"):
  416.             share = l[:- len (" Printer")].strip ()
  417.     if share == -1:
  418.             continue
  419.         rest = l[len (share):].strip ()
  420.         end = rest.find (" ")
  421.         if end == -1:
  422.             type = rest
  423.             comment = ""
  424.         else:
  425.             type = rest[:rest.find (" ")]
  426.             comment = rest[len (type):].strip ()
  427.  
  428.         if type == "Printer":
  429.             printers[share] = comment
  430.  
  431.     return printers
  432.  
  433. def printer_share_accessible (share, group = None, user = None, passwd = None):
  434.     """Returns None if the share is inaccessible.  Otherwise,
  435.     returns a dict with 'GROUP' associated with the workgroup name
  436.     of the server."""
  437.  
  438.     if not os.access (smbclient, os.X_OK):
  439.         return None
  440.  
  441.     args = [ smbclient, share ]
  442.     if os.getenv ("KRB5CCNAME"):
  443.         args.append ("-k")
  444.     elif passwd:
  445.         args.append (passwd)
  446.     else:
  447.         args.append ("-N")
  448.  
  449.     if group:
  450.         args.extend (["-W", group])
  451.  
  452.     args.extend (["-c", "quit"])
  453.     if user:
  454.         args.extend (["-U", user])
  455.  
  456.     read, write = os.pipe ()
  457.     pid = os.fork ()
  458.     if pid == 0:
  459.         os.close (read)
  460.         if write != 1:
  461.             os.dup2 (write, 1)
  462.         os.dup2 (1, 2)
  463.  
  464.         os.environ['LC_ALL'] = 'C'
  465.         os.execv (args[0], args)
  466.         sys.exit (1)
  467.  
  468.     # Parent
  469.     dict = { 'GROUP': ''}
  470.     os.close (write)
  471.     for l in os.fdopen (read, 'r').readlines ():
  472.         if l.startswith ("Domain=[") and l.find ("]") != -1:
  473.             dict['GROUP'] = l[len("Domain=["):].split ("]")[0]
  474.             break
  475.  
  476.     pid, status = os.waitpid (pid, 0)
  477.     if status:
  478.         return None
  479.  
  480.     return dict
  481.  
  482. if __name__ == '__main__':
  483.  
  484.     domains = get_domain_list ()
  485.     for domain in domains:
  486.         print domains[domain]
  487.     hosts = get_host_list_from_domain (domain)
  488.     if len(hosts) <= 0:
  489.             print "fallback to get_host_list(IP)"
  490.         hosts = get_host_list (domains[domain]['IP'])
  491.     print hosts
  492.         for host in hosts:
  493.             print hosts[host]
  494.             printers = get_printer_list (hosts[host])
  495.             print printers
  496.